package cc.creativecomputing.resonate.journal;

import cc.creativecomputing.graphics.CCDrawMode;
import cc.creativecomputing.graphics.CCGraphics;
import cc.creativecomputing.graphics.CCGraphics.CCBlendMode;
import cc.creativecomputing.graphics.CCVBOMesh;
import cc.creativecomputing.graphics.shader.CCGLSLShader;
import cc.creativecomputing.graphics.shader.CCShaderBuffer;
import cc.creativecomputing.graphics.shader.imaging.CCGPUSeperateGaussianBlur;
import cc.creativecomputing.graphics.texture.CCTexture2D;
import cc.creativecomputing.graphics.texture.filter.CCGaussianBlur;
import cc.creativecomputing.io.CCIOUtil;
import cc.creativecomputing.math.CCMath;
import cc.creativecomputing.math.CCVector2f;
import cc.creativecomputing.simulation.particles.CCGPUParticles;
import cc.creativecomputing.simulation.particles.render.CCGPUParticleRenderer;


public class MJPointSpriteParticleRenderer {

	protected CCVBOMesh _myMesh;
	protected CCShaderBuffer _myIndexTexture;
	private CCGLSLShader _myShader;
	private CCGraphics g;
	private CCVector2f _myPointSize;
	private boolean _myFadeOut = false;
	private float time = 0;
	
	private CCTexture2D _myPointSpriteTexture;
	private int _myXSplits;
	private int _myYSplits;
	private CCTexture2D _myCustomInfoTexture;
	private CCTexture2D positions;
	private CCTexture2D infos;
	
	private CCShaderBuffer _myOutputBuffer;
	
	private CCGPUSeperateGaussianBlur _myBlur;
	
	public void setTime (float theTime) {
		time = theTime;
	}
	
	public MJPointSpriteParticleRenderer (CCGraphics theGraphics, CCTexture2D thePointSpriteTexture, int theXSplits, int theYSplits) {
		_myShader = new CCGLSLShader(
			CCIOUtil.classPath(this,"shader_journal/pointsprite_vertex.glsl"),
			CCIOUtil.classPath(this,"shader_journal/pointsprite_fragment.glsl")
		);
		_myShader.load();
		
		_myPointSpriteTexture = thePointSpriteTexture;
		_myXSplits = theXSplits;
		_myYSplits = theYSplits;
		g = theGraphics;
		
		_myPointSize = new CCVector2f(1, 1 * g.width / (float)g.height);
		
		_myBlur = new CCGPUSeperateGaussianBlur(20, g.width, g.height);
		_myOutputBuffer = new CCShaderBuffer(g.width, g.height);
		_myOutputBuffer.clear();
	}
	
	public void setCustomDataTexture (CCTexture2D theCustomInfoTexture) {
		_myCustomInfoTexture = theCustomInfoTexture;
	}
	
	public void setup (int w, int h, CCTexture2D thePositions, CCTexture2D theInfos) {
		
		positions = thePositions;
		infos = theInfos;
		
		_myMesh = new CCVBOMesh(CCDrawMode.QUADS, w * h * 4 );
		_myMesh.prepareVertexData(4);
		_myMesh.prepareTextureCoordData(0, 2);
		
		float myXtexSize = 1 / (float)_myXSplits;
		float myYtexSize = 1 / (float)_myYSplits;
		System.out.println(myXtexSize+" "+myYtexSize);
		for(int x = 0; x < w; x++) {
			for(int y = 0; y < h; y++) {
			
				g.textureCoords(0, (float)x, (float)y);
				g.vertex(x,y);
				
				_myMesh.addVertex(x/(float)w,y/(float)h,-1,-1);
				_myMesh.addVertex(x/(float)w,y/(float)h, 1,-1);
				_myMesh.addVertex(x/(float)w,y/(float)h, 1, 1);
				_myMesh.addVertex(x/(float)w,y/(float)h,-1, 1);
				
				_myMesh.addTextureCoords (0, myYtexSize);
				_myMesh.addTextureCoords (myXtexSize, myYtexSize);
				_myMesh.addTextureCoords (myXtexSize, 0);
				_myMesh.addTextureCoords (0, 0);
				
			}
		}
	}

	public void draw (CCGraphics g) {
		
		g.pushAttribute();
		g.blend(CCBlendMode.ALPHA);
		g.noDepthTest();
		g.gl.glEnable(g.gl.GL_SAMPLE_ALPHA_TO_COVERAGE);
		
		_myShader.start();
		g.texture(0, positions);
		g.texture(1, infos);
		g.texture(2, _myPointSpriteTexture);
		_myShader.uniform1i("positions", 0);
		_myShader.uniform1i("infos", 1);
		_myShader.uniform1i("pointSprite", 2);
		_myShader.uniform1f("tanHalfFOV", CCMath.tan(g.camera().fov()) * g.height);
		_myShader.uniform2f("pointSize", 40, 40);
		_myShader.uniform1f("alpha", _myFadeOut ? 0 : 1);
		_myShader.uniform1f("time", time);
		
		
		_myMesh.draw(g);
		
		g.noTexture();
		_myShader.end();
		g.popAttribute();
	}
}
